<!-- 添加小程序 -->
<template>
  <el-dialog
    v-model="dialogVisible"
    width="70%"
    :title="action === 'edit' ? '编辑小程序' : action === 'add' ? '添加小程序' : '小程序详情'"
    draggable
    appendToBody
    destroyOnClose
    lockScroll
    :closeOnClickModal="false"
  >
    <base-skeleton v-if="pageLoad.loadState === true" style="width: 100%; height: 100%; min-height: 420px; padding: 0 20px"></base-skeleton>
    <template v-else-if="pageLoad.loadState === false">
      <el-form ref="elFormRef" v-auto-animate v-AutoAnimate :model="formData" :rules="rules" scrollToError :disabled="disabled">
        <el-row>
          <el-col :span="12">
            <el-form-item label="平台类型" labelWidth="9em" prop="type">
              <bubble-select-local
                v-model="formData.type!"
                labelKey="label"
                valueKey="value"
                :filterable="false"
                style="width: 100%"
                :list="[
                  { label: '抖音', value: 'mp-toutiao' },
                  { label: '快手', value: 'mp-kuaishou' },
                  { label: '微信', value: 'mp-weixin' },
                ]"
                placeholder="请选择平台类型"
              ></bubble-select-local>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="小程序名称" labelWidth="9em" prop="appName">
              <el-input v-model="formData.appName" :maxlength="32" clearable placeholder="请输入小程序名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="平台编码" labelWidth="9em" prop="appCode">
              <el-input v-model="formData.appCode" :maxlength="64" clearable placeholder="请输入平台编码 (如:dy_dsdj_01)"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="appId" labelWidth="9em" prop="appId">
              <el-input v-model="formData.appId" :maxlength="64" clearable placeholder="请输入appId"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="appSecret" labelWidth="9em" prop="appSecret">
          <el-input v-model="formData.appSecret" :maxlength="64" clearable placeholder="请输入appSecret"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-toutiao', 'mp-weixin'].includes(formData.type)" key="el-form-item-1" label="支付token令牌" labelWidth="9em" prop="payToken">
          <el-input v-model="formData.payToken" :maxlength="64" clearable placeholder="请输入支付token令牌"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-toutiao'].includes(formData.type)" key="el-form-item-2" label="抖音支付salt" labelWidth="9em" prop="paySalt">
          <el-input v-model="formData.paySalt" :maxlength="64" clearable placeholder="请输入抖音支付salt"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-toutiao'].includes(formData.type)" key="el-form-item-3" label="" labelWidth="9em" prop="privateKey">
          <template #label>
            <div style="display: flex; align-items: center; justify-content: flex-start">
              <span>抖音应用私钥</span>
              <el-popover title="抖音应用公私钥生成与配置" width="700px">
                <template #reference>
                  <el-icon><icon-ep-question-filled></icon-ep-question-filled></el-icon>
                </template>
                <div>
                  <span>1.抖音应用公私钥为RSA加密的公私钥,可自行生成,也可通过</span>
                  <a href="https://developer.open-douyin.com/docs/openapi-explorer/sign">抖音签名调试工具</a>
                  <span>或</span>
                  <a href="https://www.bejson.com/enc/rsa/">在线密匙生成网站</a>
                  <span>生成</span>
                </div>
                <div style="margin-top: 10px">
                  <span>2. 生成密匙后需要把公匙上传到 抖音开放平台-开发-开发配置--密匙设置-应用公匙中</span>
                </div>
                <div style="margin-top: 10px">
                  <span>3. 生成密匙后还需要把私匙上传到这里,这里会自动去除私匙的空格换行以及“-----BEGIN PRIVATE KEY----”等前/后缀,无需自行去除</span>
                </div>
              </el-popover>
            </div>
          </template>
          <el-input
            v-model="formData.privateKey"
            clearable
            :formatter="(val: string) => val.replace(/\s/g, '').replace('-----BEGINPRIVATEKEY-----', '').replace('-----ENDPRIVATEKEY-----', '')"
            :parser="(val: string) => val.replace(/\s/g, '').replace('-----BEGINPRIVATEKEY-----', '').replace('-----ENDPRIVATEKEY-----', '')"
            placeholder="请输入抖音应用私钥 (会自动去除空格换行以及“-----BEGIN PRIVATE KEY----”等前/后缀)"
          ></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-toutiao'].includes(formData.type)" key="el-form-item-4" label="抖音平台公钥" labelWidth="9em" prop="platformPublicKey">
          <el-input
            v-model="formData.platformPublicKey"
            clearable
            :formatter="(val: string) => val.replace(/\s/g, '').replace('-----BEGINPUBLICKEY-----', '').replace('-----ENDPUBLICKEY-----', '')"
            :parser="(val: string) => val.replace(/\s/g, '').replace('-----BEGINPUBLICKEY-----', '').replace('-----ENDPUBLICKEY-----', '')"
            placeholder="请输入抖音平台公钥 (会自动去除空格换行以及“-----BEGIN PUBLIC KEY-----”等前/后缀)"
          ></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-toutiao'].includes(formData.type)" key="el-form-item-5" label="代码上传密钥" labelWidth="9em" prop="uploadKey">
          <el-input v-model="formData.uploadKey" clearable placeholder="请输入抖音平台代码上传密钥"></el-input>
        </el-form-item>
        <el-form-item
          v-if="action !== 'add' && ['mp-toutiao'].includes(formData.type)"
          key="el-form-item-6"
          label="交易规则标签组"
          labelWidth="9em"
          prop="tagGroupId"
        >
          <el-input v-model="formData.tagGroupId" :maxlength="0" clearable placeholder="请输入交易规则标签组" disabled></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-weixin'].includes(formData.type)" key="el-form-item-7" label="微信原始id" labelWidth="9em" prop="appOriginalId">
          <el-input v-model="formData.appOriginalId" :maxlength="64" clearable placeholder="请输入微信原始id"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-weixin'].includes(formData.type)" key="el-form-item-8" label="微信支付应用ID" labelWidth="9em" prop="offerId">
          <el-input v-model="formData.offerId" :maxlength="64" clearable placeholder="请输入微信支付应用ID"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-weixin'].includes(formData.type)" key="el-form-item-9" label="微信沙箱AppKey" labelWidth="9em" prop="testAppKey">
          <el-input v-model="formData.testAppKey" :maxlength="64" clearable placeholder="请输入微信沙箱AppKey"></el-input>
        </el-form-item>
        <el-form-item v-if="['mp-weixin'].includes(formData.type)" key="el-form-item-10" label="微信现网AppKey" labelWidth="9em" prop="prodAppKey">
          <el-input v-model="formData.prodAppKey" :maxlength="64" clearable placeholder="请输入微信现网AppKey"></el-input>
        </el-form-item>
        <el-form-item label="" labelWidth="9em" prop="payNotifyUrl">
          <template #label>
            <div style="display: flex; align-items: center; justify-content: flex-start">
              <span>支付通知地址</span>
              <el-popover title="支付通知地址生成与配置" width="700px">
                <template #reference>
                  <el-icon><icon-ep-question-filled></icon-ep-question-filled></el-icon>
                </template>
                <div>
                  <span>1.这里配置后还需要把通知地址配置到对应小程序开放平台的支付回调地址中去</span>
                </div>
              </el-popover>
            </div>
          </template>
          <el-input v-model="formData.payNotifyUrl" :maxlength="200" clearable placeholder="请输入支付通知地址"></el-input>
        </el-form-item>
        <el-form-item label="备注" labelWidth="9em" prop="remark">
          <el-input v-model="formData.remark" :maxlength="12" clearable placeholder="请输入备注"></el-input>
        </el-form-item>
        <div v-if="['mp-toutiao'].includes(formData.type)" style="display: flex; flex-direction: column">
          <span style="font-size: 14px; font-weight: bold; color: #ff0000">温馨提醒</span>
          <span style="margin-top: 10px; font-size: 14px; color: #ff0000">
            1.抖音支付还需在 抖音开放平台-能力-解决方案-通用-交易类小程序通用下开通
            【进件回调能力】、【通用交易系统支付结果消息能力】、【通用交易系统退款结果消息能力】、【通用交易系统OpenApi接口能力】
          </span>
        </div>
        <el-form-item v-if="!disabled" key="el-form-item-11" labelWidth="0em">
          <div style="width: 100%; padding-top: 20px">
            <el-button style="width: 100%" type="success" :disabled="loading" :loading="loading" @click="submit">保存</el-button>
          </div>
        </el-form-item>
      </el-form>
    </template>
    <base-empty
      v-else
      style="height: 100%"
      :description="pageLoad.description || ''"
      :imageSize="240"
      :loadState="pageLoad.loadState"
      :pageLoadButton="[{ text: '重新加载', callBack: getBaseDataAxios }]"
    ></base-empty>
  </el-dialog>
</template>

<script setup lang="ts">
  import type { FormInstance, FormRules } from 'element-plus';
  import IconEpQuestionFilled from '~icons/ep/question-filled';
  import { vAutoAnimate } from '@formkit/auto-animate/vue';
  import { type MiniProgramListItem, addMiniProgram, editMiniProgram } from '@/api/app-management';
  type $EditShowData = {
    /** 操作 */
    action: 'edit';
    /** 记录 */
    record: MiniProgramListItem;
    /** 审核后的回调 */
    editCallBack?: () => void;
  };

  type $AddShowData = {
    /** 操作 */
    action: 'add';
    /** 审核后的回调 */
    addCallBack?: () => void;
  };

  type $DetailsShowData = {
    /** 操作 */
    action: 'details';
    record: MiniProgramListItem;
  };
  type $ShowData = $AddShowData | $DetailsShowData | $EditShowData;

  const pageLoad = shallowReactive<$PageLoad>({ loadState: true, description: '' });

  let addCallBack: $AddShowData['addCallBack'] = undefined;
  let editCallBack: $EditShowData['editCallBack'] = undefined;

  const dialogVisible = ref(false);
  const elFormRef: Ref<FormInstance | null> = ref(null);
  const action = ref<'add' | 'details' | 'edit'>();
  const loading = ref(false);

  const disabled = computed(() => action.value === 'details');

  const formData = reactive<MiniProgramListItem>({
    socialId: undefined,
    appName: '',
    type: 'mp-toutiao',
    appCode: '',
    appId: '',
    appSecret: '',
    payToken: '',
    paySalt: '',
    privateKey: '',
    platformPublicKey: '',
    tagGroupId: '',
    uploadKey: '',
    // wx
    appOriginalId: '',
    offerId: '',
    testAppKey: '',
    prodAppKey: '',
    payNotifyUrl: '',
    redirectUrl: '',
    remark: '',
  });

  const rules = computed(() => {
    const _rules: FormRules<MiniProgramListItem> = {
      appName: [{ required: true, type: 'string', message: '请输入小程序名称', trigger: ['blur', 'change'] }],
      type: [{ required: true, type: 'string', message: '请选择平台类型', trigger: ['blur', 'change'] }],
      appCode: [{ required: true, type: 'string', message: '请输入平台编码', trigger: ['blur', 'change'] }],
      appId: [{ required: true, type: 'string', message: '请输入appId', trigger: ['blur', 'change'] }],
      appSecret: [{ required: true, type: 'string', message: '请输入appSecret', trigger: ['blur', 'change'] }],
      payToken: [{ required: true, type: 'string', message: '请输入支付token令牌', trigger: ['blur', 'change'] }],
      paySalt: [{ required: true, type: 'string', message: '请输入抖音支付salt', trigger: ['blur', 'change'] }],
      uploadKey: [{ required: true, type: 'string', message: '请输入代码上传密钥', trigger: ['blur', 'change'] }],
      privateKey: [
        { required: true, type: 'string', message: '请输入抖音应用私钥', trigger: ['blur', 'change'] },
        {
          type: 'string',
          message: '不需要-----BEGIN PRIVATE KEY-----等前/后缀',
          validator(_rule, value, callback) {
            if (value && value.includes('----BEGIN')) {
              callback(new Error('不需要-----BEGIN PRIVATE KEY-----等前/后缀'));
            } else {
              callback();
            }
          },
        },
      ],
      platformPublicKey: [
        { required: true, type: 'string', message: '请输入抖音平台公钥', trigger: ['blur', 'change'] },
        {
          type: 'string',
          message: '不需要-----BEGIN PUBLIC KEY-----等前/后缀',
          validator(_rule, value, callback) {
            if (value && value.includes('----BEGIN')) {
              callback(new Error('-----BEGIN PUBLIC KEY-----等前/后缀'));
            } else {
              callback();
            }
          },
        },
      ],
      appOriginalId: [{ required: true, type: 'string', message: '请输入微信原始id', trigger: ['blur', 'change'] }],
      offerId: [{ required: true, type: 'string', message: '请输入微信支付应用ID', trigger: ['blur', 'change'] }],
    };
    return _rules;
  });

  /**
   * 提交
   */
  async function submit() {
    try {
      await elFormRef.value?.validate();
      try {
        loading.value = true;

        if (action.value === 'edit') {
          await editMiniProgram(formData);
          typeof editCallBack === 'function' && editCallBack();
        } else {
          await addMiniProgram(formData);
          typeof addCallBack === 'function' && addCallBack();
        }
        loading.value = false;
        hide();
      } catch (error) {
        loading.value = false;
        ElToast.error(error.msg || '提交失败，-BD001');
      }
    } catch (error) {
      ElToast.error('提交失败，请完善表单，-BD002');
    }
  }

  /**
   * 显示
   */
  function show(data: $ShowData) {
    action.value = data.action;

    if (data.action === 'edit' || data.action === 'details') {
      formData.type = data.record.type;
      formData.appName = data.record.appName;
      formData.appCode = data.record.appCode;
      formData.appId = data.record.appId;
      formData.appSecret = data.record.appSecret;
      formData.payToken = data.record.payToken;
      formData.paySalt = data.record.paySalt;
      formData.privateKey = data.record.privateKey;
      formData.uploadKey = data.record.uploadKey;
      formData.platformPublicKey = data.record.platformPublicKey;
      formData.tagGroupId = data.record.tagGroupId;
      formData.appOriginalId = data.record.appOriginalId;
      formData.offerId = data.record.offerId;
      formData.testAppKey = data.record.testAppKey;
      formData.prodAppKey = data.record.prodAppKey;
      formData.payNotifyUrl = data.record.payNotifyUrl;
      formData.redirectUrl = data.record.redirectUrl;
      formData.remark = data.record.remark;
      formData.socialId = data.record.socialId || undefined;
    } else {
      formData.appName = '';
      formData.type = 'mp-toutiao';
      formData.appCode = '';
      formData.appId = '';
      formData.appSecret = '';
      formData.payToken = '';
      formData.paySalt = '';
      formData.privateKey = '';
      formData.platformPublicKey = '';
      formData.tagGroupId = '';
      formData.appOriginalId = '';
      formData.uploadKey = '';
      formData.offerId = '';
      formData.testAppKey = '';
      formData.prodAppKey = '';
      formData.payNotifyUrl = '';
      formData.redirectUrl = '';
      formData.remark = '';
    }

    addCallBack = 'addCallBack' in data && typeof data.addCallBack === 'function' ? data.addCallBack : undefined;
    editCallBack = 'editCallBack' in data && typeof data.editCallBack === 'function' ? data.editCallBack : undefined;

    dialogVisible.value = true;

    getBaseDataAxios();
  }

  /**
   * 隐藏
   */
  function hide() {
    dialogVisible.value = false;
  }

  /** 请求 */
  function getBaseDataAxios() {
    try {
      pageLoad.loadState = true;
      //
      pageLoad.loadState = false;
    } catch (error) {
      pageLoad.loadState = 'err';
      pageLoad.description = String((error as Record<string, unknown>).msg || '') || '获取数据失败';
    }
  }

  defineExpose({ show, hide });
</script>
